extractJsonMiddleware

Extracts JSON from text-only model output. For models that wrap their structured response in markdown code fences (```json {...} ``` ) or mix prose with the JSON, this strips the surrounding text and surfaces just the JSON object.

Mirrors v6's extractJsonMiddleware. Useful when Output is set on generateText but the underlying model doesn't natively support structured output and emits free text — the on-device Gemma path.

Streaming follows v6's state machine: hold text-start until a possible markdown fence prefix is resolved, then stream through text while retaining a 12-character suffix buffer so a closing fence can be stripped without buffering the whole response.

Truncation robustness. A truncated generation (context exhausted, max tokens, cancellation) leaves the JSON region open — {"a":1 instead of {"a":1}. extractAndRepairJson runs the extracted region through parsePartialJson / fixJson, so a cut-off object is repaired into a parseable one rather than failing downstream Output.decode. This is the on-device "unstable as context grows" failure mode the repair layer (gap #13) exists to absorb. @param transform optional custom text transform. When supplied, streaming text is buffered until TextEnd, matching v6 because an arbitrary transform cannot be applied incrementally.